\section{ResultSet Wrapper}

Esta primeira solução é independente da implementação do driver, isto é, funciona para qualquer driver que existe. A ideia base consiste em criar um mecanismo que controle os acessos concorrentes a um objecto result set partilhado, e providencie uma implementação dos serviços garantindo o acesso correcto ao result set, resolvendo assim os problemas identificados anteriormente (secção \ref{sec:problema}).

O acesso correcto ao result set implica que para cada entidade que lhe acede seja guardado o número da linha do result set em que ele se encontra a trabalhar, e quando voltar a ser a entidade activa o result set volta a encontrar-se nessa linha.
Para tal é necessário que a linha do result set em que cada entidade se encontra a trabalhar seja guardada quando existe troca de entidade activa, e seja restaurada a linha quando voltar a ser a entidade activa.
A operação que guarda o número da linha do result set denomina-se por \textbf{salvaguarda de contexto} e a operação que move o result set para a linha guardada denomina-se por \textbf{restauração de contexto}.

A Figura \ref{fig:cursor-wrapper-overview} apresenta o diagrama de classes da solução ResultSet Wrapper.

\begin{figure}[H]
  \caption{Diagrama de classes da solução ResultSet Wrapper.}
  \label{fig:cursor-wrapper-overview}
  \centering
  \includegraphics[width=13cm]{images/model/cursor-wrapper-overview}
\end{figure}

A solução consiste em criar cursores cliente que encapsulam (wrap) e partilham a mesma instância de um ResultSet. A cada thread que pretende trabalhar sobre o result set é lhe atribuído um cursor cliente. O processo de salvaguarda/restauro de contexto é realizado pelo cursor cliente, e é totalmente transparente para o utilizador. Isto significa que o modo de utilização desta solução é rigorosamente igual à utilização da interface ResultSet.

Existem quatro tipos de cursores: 
\begin{description}
  \item[CursorForwardReadOnly] \hfill \\
  Wrapper para um result set FORWARD\_ONLY/READ\_ONLY.
  \item[CursorForwardUpdate] \hfill \\
  Wrapper para um result set FORWARD\_ONLY/UPDATABLE.
  \item[CursorScrollReadOnly] \hfill \\
  Wrapper para um result set SCROLLABLE\_SENSITIVE/READ\_ONLY.
  \item[CursorScrollUpdate] \hfill \\
  Wrapper para um result set SCROLLABLE\_SENSITIVE/UPDATABLE.
\end{description}

Cada tipo de cursor implementa os métodos da interface \emph{ResultSet} que fazem sentido, lançando uma excepção dizendo que a operação não é suportada no caso contrário. Por exemplo, o CursorScrollReadOnly implementa os métodos relacionados com o movimento do cursor, e lança excepção se se tentar invocar um método de update, enquanto que o CursorForwardUpdate suporta os métodos de update e lança uma excepção se se tentar mover o cursor para uma linha específica (método absolute). 

A gestão dos contextos dos cursores cliente é realizada pelos próprios cursores. 
Cada um tem a noção da linha do result set onde se encontra acedendo à variável \texttt{currentRow} da própria classe. 
Assim, quando é o cursor cliente activo, se for necessário recupera o seu contexto, movendo o result set para a linha onde se encontrava a trabalhar.
A detecção da mudança do cursor activo é realizada com o auxílio da variável \texttt{currentCursor} que tem visibilidade ao nível da classe \emph{AbstractCursor} e que guarda o identificador do cursor activo. 
Quando um cursor entra em execução, o primeiro procedimento é verificar se o valor de currentCursor é igual ao seu identificador (\texttt{id}), se for igual então não é necessário mover o result set, porque ele foi o último cursor a trabalhar com o result set, caso contrário invoca o método do result set que o posiciona na linha onde se encontrava a trabalhar anteriormente. O trabalho sobre o result set tem que ser realizado num regime de acesso exclusivo, para o obter esse acesso exclusivo (\gls{lock}) é utilizada a variável \texttt{lock} que é uma instância da classe \emph{ReentrantLock}. Esta classe providencia o mesmo comportamento e semântica que o monitor explícito acedido usando métodos e blocos \texttt{synchronized}, mas com funcionalidades extra \cite{REENTRANTLOCK}.

\subsection{Utilização}

A criação de um result set wrapper é realizada por intermédio da interface \emph{ICursorFactory}. Esta interface fornece um serviço para construir cada um dos tipos de cursor (CursorForwardReadOnly, CursorForwardUpdate, CursorScrollReadOnly e CursorScrollUpdate). A interface da fábrica de cursores é implementada pela classe CursorFactoryImpl, que recebe no seu construtor o objecto result set que será mais tarde partilhado pelos cursores. No acto de construção de um cursor é verificado se o result set encapsulado é compatível com o tipo de cursor que se está a pedir, lançando-se uma excepção numa situação de incompatibilidade. Por exemplo, se o método createForwardRead é invocado e o result set é do tipo SCROLLABLE\_SENSITIVE/READ\_ONLY uma excepção a explicar a situação é criada e lançada. A Figura \ref{fig:cursor-wrapper-factory} apresenta o diagrama de classes com a fábrica de cursores.

\begin{figure}[H]
  \caption{Diagrama das classes envolvidas na utilização das solução Cursor Wrapper.}
  \label{fig:cursor-wrapper-factory}
  \centering
  \includegraphics[width=11cm]{images/model/cursor-wrapper-factory}
\end{figure}

Para utilizar esta solução primeiro cria-se um objecto ResultSet, como se criaria habitualmente utilizando o método executeQuery da interface Statement. 
Em seguida cria-se uma instância da fábrica de cursores passando como argumento o result set ao seu construtor. 
O último passo consiste em utilizar um dos serviços disponibilizados pela interface da fábrica para criar o wrapper do result set desejado.

A Listagem \ref{lst:cursor-wrapper-usage} exemplifica a utilização da solução ResultSet Wrapper para um result set do tipo TYPE\_FORWARD\_ONLY/CONCUR\_UPDATABLE.

\lstinputlisting[firstline=1,lastline=8,texcl=true,caption=Criação de um ResultSet Wrapper.,label=lst:cursor-wrapper-usage]{code/cursor-wrapper-usage.java}

O objecto \texttt{stmt} é uma instância de \emph{Statement} e foi criado com o tipo adequado ao tipo de wrapper criado na listagem. O argumento \texttt{sql} é uma String que contém a \gls{statement} que dá origem ao result set.
